package com.lmaos.basetools.base.calculate;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.lmaos.allcontrol.beancontrol.field_.FieldUtils;
import com.lmaos.basetools.base.SNumberUtils;

public class SCalculate {
	public final static String TYPE_JAVASCRIPT = "javascript";
	SCalculateMode calculateMode = null;
	public SCalculate(String type) {
		if(type.toLowerCase().equals("javascript")){
			calculateMode = new SCalculateModeJavaScript();
		}else{
			calculateMode = new SCalculateModeJavaScript();
		}
	}
	public SCalculate() {
		calculateMode = new SCalculateModeJavaScript();
	}
	
	public double calculate(String format){
		return calculateMode.calculate(format);
	}
	public double calculate(Object obj ,String format){
		return calculate(obj, format, null,null);
	}	
	public double calculate(Object obj ,String format,Map<String, Double> specialValues, Map<String, Double> ruleValues){
		StringBuilder result = new StringBuilder(format.length()+30);
		StringBuilder field = new StringBuilder();
		boolean iskey = false;
		for (int i = 0; i < format.length(); i++) {
			char c = format.charAt(i);
			
			if(isLetters(c)||c=='_'||c=='$'||c=='#'||iskey&&isNumber(c)){
				iskey = true;
				field.append(c);
				if(i == format.length() - 1){
					double value = getValue(field, obj, specialValues,ruleValues, 0);
					result.append(value);
				}
			}else if(iskey){
				double value = getValue(field, obj, specialValues,ruleValues, 0);
				result.append(value);
				result.append(c);
				iskey = false;
				field = new StringBuilder();
			}else{
				result.append(c);
			}
		}
		return calculateMode.calculate(result.toString());
	}
	// 是否是数学符号
	public boolean isSymbol(char c){
		return c=='+'||c=='-'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='{'||c=='}'||c=='['||c==']'||c=='%'||c=='&'||c=='|'||c=='^';
	}
	// 是否是字母
	public boolean isLetters(char c){
		return c>='a'&&c<='z'||c>='A'&&c<='Z';
	}
	// 是否是数字
	public boolean isNumber(char c){
		return c>='0'&&c<='9';
	}
	
	/**
	 * 说明：获得值		<br>
	 * 时间：2017年7月27日 下午2:19:44
	 *
	 * @param field
	 * @param obj
	 * @param specialValues
	 * @param ruleValues 规则值 key = field.value
	 * @param def
	 * @return
	 */
	private double getValue(StringBuilder field, Object obj ,Map<String, Double> specialValues,Map<String, Double> ruleValues,double def){
		Object value = def;
		if(field.charAt(0)=='#'){
			if(specialValues!=null){
				value = specialValues.get(field.substring(1));
			}
		}else{
			value = FieldUtils.getFieldValue(obj, field.toString());
		}
		if(ruleValues!=null){// 规则值 key = field.value
			Object ruleValue = ruleValues.get(field.toString()+"."+value);
			if(ruleValue == null){// 匹配全部指定的值 key = field.*
				ruleValue = ruleValues.get(field.toString()+".*");
			}
			if(ruleValue!=null){
				value = ruleValue;
			}
		}
		return SNumberUtils.toDouble(value,def);
	}
	public double calculate(Collection objs ,String format){
		return calculate(objs, format, null,null);
	}
	public double calculate(Collection objs ,String format,Map<String, Double> specialValues, Map<String, Double> ruleValues){
		double values = 0;
		for (Object obj : objs) {
			values +=calculate(obj, format, specialValues,ruleValues);
		}
		return values;
	}
	
	public static class A{
		int a = 10;
		int b = 20;
		int c = 30;
		int id= 8009;
	}
	
	public static void main(String[] args) {
		SCalculate c = new SCalculate(SCalculate.TYPE_JAVASCRIPT);
		Map<String, Double> ruleValues = new HashMap<String, Double>();
		ruleValues.put("id.8009", 100.0);
		ruleValues.put("id.*", 0.0);
		System.out.println(c.calculate(new A(),"(a+b)*c+id",null,ruleValues));
		System.out.println(c.calculate(new A(),"(5+b)*3"));
	}
}
